﻿Namespace Compiler.Semantic

    Public NotInheritable Class SymbolCompareRule

        Shared Sub New()
            sm_ignoreCase = True
        End Sub

        Private Shared sm_ignoreCase As Boolean
        Public Shared Property IgnoreCase() As Boolean
            Get
                Return sm_ignoreCase
            End Get
            Set(ByVal value As Boolean)
                sm_ignoreCase = value
            End Set
        End Property

    End Class

    Public NotInheritable Class Symbol
        Implements IComparable(Of Symbol), IEquatable(Of Symbol)

        Private Shared m_uniqueNameTable As IDictionary(Of String, Symbol) = New Dictionary(Of String, Symbol)

        Private ReadOnly m_Name As String

        Public ReadOnly Property Name() As String
            Get
                Return m_Name
            End Get
        End Property

        Private Sub New(ByVal name As String)
            m_Name = name
        End Sub

        Public Overrides Function ToString() As String
            Return m_Name
        End Function

        Public Overrides Function Equals(ByVal obj As Object) As Boolean
            If TypeOf obj Is Symbol Then
                Return Equals(DirectCast(obj, Symbol))
            Else
                Return False
            End If
        End Function

        Public Overrides Function GetHashCode() As Integer
            Return m_Name.GetHashCode
        End Function

        Public Function CompareTo(ByVal other As Symbol) As Integer Implements System.IComparable(Of Symbol).CompareTo
            If SymbolCompareRule.IgnoreCase Then
                Return String.Compare(m_Name, other.m_Name, StringComparison.InvariantCultureIgnoreCase)
            Else
                Return String.Compare(m_Name, other.m_Name, StringComparison.InvariantCulture)
            End If
        End Function

        Public Overloads Function Equals(ByVal other As Symbol) As Boolean Implements System.IEquatable(Of Symbol).Equals
            If SymbolCompareRule.IgnoreCase Then
                Return m_Name.Equals(other.m_Name, StringComparison.InvariantCultureIgnoreCase)
            Else
                Return m_Name.Equals(other.m_Name, StringComparison.InvariantCulture)
            End If
        End Function

        '==============================Static Factory==============================
        Public Shared Function [Get](ByVal name As String) As Symbol

            If name Is Nothing Then Throw New ArgumentNullException("name")

            Dim uniqueNameStr As String = String.Intern(name)
            Dim newSymbol As Symbol = Nothing

            If Not m_uniqueNameTable.TryGetValue(uniqueNameStr, newSymbol) Then
                newSymbol = New Symbol(uniqueNameStr)
                m_uniqueNameTable.Add(uniqueNameStr, newSymbol)
            End If

            Return newSymbol
        End Function

        Public Shared Operator =(ByVal a As Symbol, ByVal b As Symbol) As Boolean
            If a Is Nothing Then
                If b Is Nothing Then Return True Else Return False
            End If

            Return a.Equals(b)
        End Operator

        Public Shared Operator <>(ByVal a As Symbol, ByVal b As Symbol) As Boolean
            If a Is Nothing Then
                If b Is Nothing Then Return False Else Return True
            End If

            Return Not a.Equals(b)
        End Operator
    End Class

End Namespace
